问题的由来
JavaScript代码:

//JavaScript
console.log(0.3 - 0.2 == 0.2 - 0.1) //false

Python代码:

#!/usr/bin/env python
# -*- coding:utf8 -*-
print 0.3 - 0.2 == 0.2 - 0.1 #False

同样的原因:浮点数在数字计算机中表示不精确的问题。

JavaScript代码:

//JavaScript
console.log(0.3 - 0.2) //0.09999999999999998
console.log(0.2 - 0.1) //0.1

Python代码:

#!/usr/bin/env python
# -*- coding:utf8 -*-    
print 0.3 - 0.2  #0.09999999999999998
print 0.2 - 0.1  #0.1

都知道在数字计算机中用二进制位来表示数据,数字当然也不例外。

1 定点表示法

二进制小数的表示方式为:
bmbm-1…b3b2b1.b1b2b3…b-n+1b-n
上式表示的数值为
b = sum(bi * 2i),其中-n <= i <= m
这样就能很自然的表示我们的小数,这种小数点固定的表示方法叫做定点表示法(见名知意哦!)

然而,我们很快看出他的问题了,假设计算机字长为64位,我们要表示一个264的数字就已经把数位占完了,再大一丁点的数就没法表示了,比如说再大0.1,总得要一位表示小数吧?搞不定~~

于是就有了下面的表示方法,有定点,自然就会有不定点,这种小数点不固定的方法(望文生义哦!)叫做浮点表示法(小数点浮动,^_^),这是计算机中普遍使用的表示方法。

2 浮点表示法

浮点表示法就数位分为符号(sign)、指数(exponent)、有效位数(significant)(尾数)三部分:
32位浮点数(单精度浮点数)表示:1位符号位,8位指数,23位尾数

31———————————-0

+-+——–+———————–+

64位浮点数(双精度浮点数)表示:1位符号位,11位指数,52位尾数,能进一步提高精度。

63—————————————————————–0

+-+———–+—————————————————-+

于是对于一个数b = (-1)s * M * 2E

综上可以看出浮点数的表示本身就不是精确值,精确的是2-i的和
所以
0.3 = 2-2+2-5+2-6+2-9…..
0.2 = 2-3+2-4+2-7+2-8…..
0.1 = 2-4+2-6+2-7+2-8…..
省略号表示凑够尾数的有效位数为止。

由此可以看出,确实是很难用等于来判断浮点数的取值。

解决办法:
A-B <= 误差范围,差不多就行了
比如说:
(0.3-0.2) - (0.2-0.1) <= 0.0000000001
或者
(0.3-0.2) - (0.2-0.1) <= 1.0e-10

未完待续。。。

最后更新: 2022年03月02日 03:32

原始链接: http://rawbin-.github.io/dev-general/2015-03-31-ieee-745/

× 赞赏这个人~
打赏二维码